﻿using Microsoft.AspNetCore.JsonPatch.Internal;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using TyMES.Model.Record;
using WalkingTec.Mvvm.Core;

namespace TyMES.Services
{
	public class SPCService
	{
		private readonly List<double> A = new() {0, 0, 2.121, 1.732, 1.500 };
		private readonly List<double> A2 = new() {0, 0, 1.880, 1.023, 0.729, 0.577, 0.483, 0.419, 0.373, 0.337, 0.308, 0.285, 0.266, 0.249, 0.235, 0.223, 0.212, 0.203, 0.194, 0.187, 0.180 };
		private readonly List<double> A3 = new() { };
		private readonly List<double> B3 = new() { };
		private readonly List<double> B4 = new() { };
		private readonly List<double> B5 = new() { };
		private readonly List<double> B6 = new() { };
		private readonly List<double> D1 = new() { };
		private readonly List<double> D2 = new() { };
		private readonly List<double> D3 = new() {0, 0, 0, 0, 0, 0, 0, 0.076, 0.136, 0.184, 0.223, 0.256, 0.283, 0.307, 0.328, 0.347, 0.363, 0.378, 0.391, 0.403, 0.415};
		private readonly List<double> D4 = new() {0, 0, 3.267, 2.574, 2.282, 2.114, 2.004, 1.924, 1.864, 1.816, 1.777, 1.744, 1.717, 1.693, 1.672, 1.653, 1.637, 1.622, 1.608, 1.597, 1.585};

		private readonly List<double> c4 = new() { };
		private readonly List<double> c4_1 = new() { };
		private readonly List<double> d2 = new() { };
		private readonly List<double> d2_1 = new() { };

		private readonly IServiceScope serviceScope;
		private readonly WTMContext context;

		public SPCService(IServiceScopeFactory serviceScopeFactory)
		{
			var sp = this.serviceScope.ServiceProvider;
			this.context = sp.GetRequiredService<WTMContext>();
		}

		// 获取分析数据
		private List<ProduceDataRecord> GetAnalysisData(string stationCode, int num, int len)
		{
			var res = this.context.DC.Set<ProduceDataRecord>().Where(e=>e.StationCode == stationCode).OrderByDescending(e=>e.CreateTime).Take(num * len).ToList();
			return res;
		}

		// num-组数  len-组内长度 
		private List<List<double>> GetAnalysisData(int order, int num, int len, string stationCode, int type)
		{
			List<ProduceDataRecord> res = GetAnalysisData(stationCode, num, len);
			string[] separators = new string[] { "*" };
			List<List<double>> data = new List<List<double>> ();
			for(int i = 0; i < num; i++)
			{
				data.Add(new List<double>());
				for(int j = 0; j < len; j++)
				{
					string[] result = res[i*len+j].Data.Split(separators, StringSplitOptions.RemoveEmptyEntries);
					double paraData = (type == 0)? double.Parse(result[order]): double.Parse(result[order + 20]);					
					data[i].Add(paraData);
				}
			}
			return data;
		}

		// 获取xbar数据
		private List<double> GetXBar(List<List<double>> data) 
		{
			List<double> res = new List<double>();
			int count1 = data.Count;
			int count2 = data[0].Count;
			for(int i = 0; i < count2; i++)
			{
				double sum = 0;
				for(int j = 0; j < count1; j++)
				{
					sum += data[j][i];
				}
				res.Add(sum / count2);
			}
			return res;
		}

		// 获取r数据
		private List<double> GetR(List<List<double>> data)
		{
			List<double> res = new List<double>();
			int count1 = data.Count;
			int count2 = data[0].Count;
			for (int i = 0; i < count2; i++)
			{
				double min = data[0][i];
				double max = data[0][i];
				for (int j = 1; j < count1; j++)
				{
					min = Math.Min(min, data[j][i]);
					max = Math.Max(max, data[j][i]);
				}
				res.Add(max - min);
			}
			return res;
		}

		// SPC分析
		public SPCResult Analysis(int order, int num, int len, string stationCode, int type = 0)
		{
			List<List<double>> data = GetAnalysisData(order, num, len, stationCode, type);
			List<double> xbar = GetXBar(data);
			List<double> r = GetR(data);

			double totalXBar = xbar.Average();
			double totalR = r.Average();

			double xbar_lcl = Get_R_LCL_BAR(totalXBar, totalR, num);
			double xbar_ucl = Get_R_UCL_BAR(totalXBar, totalR, num);

			double r_lcl = Get_R_LCL_R(totalR, num);
			double r_ucl = Get_R_UCL_R(totalR, num);
			List<double> xbarList = new List<double> { xbar_lcl, totalXBar, xbar_ucl };
			List<double> rList = new List<double> { r_lcl, totalR, r_ucl };

			return new SPCResult { Data = data, Result1 = xbar, Result2 = xbarList, Result3 = r, Result4 = rList};
		}

		// x-bar-r x-bar图 均值极差控制图
		// 下限
		private double Get_R_LCL_BAR(double xbar, double rbar, int num)
		{
			return xbar - A2[num] * rbar; 
		}

		// 上限
		private double Get_R_UCL_BAR(double xbar, double rbar, int num)
		{
			return xbar + A2[num] * rbar;
		}

		// x-bar-r r图
		// 下限
		private double Get_R_LCL_R(double xbar, int num)
		{
			return D3[num] * xbar;
		}

		// 上限
		private double Get_R_UCL_R(double xbar, int num)
		{
			return D4[num] * xbar;
		}


		// x-mr  单值-移动极差控制图
	}

	public class SPCResult
	{
		public List<List<double>> Data { get; set; }
		public List<double> Result1 { get; set; }
		public List<double> Result2 { get; set; }
		public List<double> Result3 { get; set; }
		public List<double> Result4 { get; set; }
	}
}
